home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / cpp112.zoo / src / comment.c < prev    next >
C/C++ Source or Header  |  1994-07-07  |  6KB  |  227 lines

  1.  
  2. /*---------------------------------------------------------------------*\
  3. |                                    |
  4. | CPP -- a stand-alone C preprocessor                    |
  5. | Copyright (c) 1993 Hacker Ltd.        Author: Scott Bigham    |
  6. |                                    |
  7. | Permission is granted to anyone to use this software for any purpose    |
  8. | on any computer system, and to redistribute it freely, with the    |
  9. | following restrictions:                        |
  10. | - No charge may be made other than reasonable charges for repro-    |
  11. |     duction.                                |
  12. | - Modified versions must be clearly marked as such.            |
  13. | - The author is not responsible for any harmful consequences of    |
  14. |     using this software, even if they result from defects therein.    |
  15. |                                    |
  16. | comment.c -- comment and whitespace processing            |
  17. \*---------------------------------------------------------------------*/
  18.  
  19. #include <stddef.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include <stdlib.h>
  23. #include "global.h"
  24.  
  25. #define SPC_GRAN 16
  26. #define LINEBUF 128
  27.  
  28. char *the_comment;
  29. size_t len_comment;
  30.  
  31. static char SC_nested[] = "nested comment (began at line %lu)",
  32.         SC_unterm[] = "unterminated comment (began at line %ld)";
  33. /*
  34.    find_start_comment() -- return a pointer to the first comment-start
  35.    sequence after |s|, or |NULL| if none is found
  36. */
  37. static char *find_start_comment(s)
  38.   register char *s;
  39. {
  40.   register int in_dq = 0, in_sq = 0;
  41.  
  42.   for (;;) {
  43.     switch (*s++) {
  44.     case '\0':
  45.       return NULL;
  46.     case '\\':
  47.       s++;
  48.       continue;
  49.     case '"':
  50.       if (!in_sq)
  51.     in_dq ^= 1;
  52.       break;
  53.     case '\'':
  54.       if (!in_dq)
  55.     in_sq ^= 1;
  56.       break;
  57.     case '/':
  58.       if (!in_dq && !in_sq && *s == '*')
  59.     return s - 1;
  60.     }
  61.   }
  62. }
  63.  
  64. /*
  65.    find_end_comment() -- return a pointer to the first character after the
  66.    current comment, or end of line if the comment does not end on this line.
  67. */
  68. static char *find_end_comment(s)
  69.   register char *s;
  70. {
  71.   for (; *s; s++) {
  72.     if (*s == '*' && s[1] == '/')
  73.       return s + 2;
  74.   }
  75.   return NULL;
  76. }
  77.  
  78. /*
  79.    nest_check() -- examine the body of a comment for comment-start sequences.
  80.    Return 1 if one is found, 0 if not.
  81. */
  82. static int nest_check(s, t)
  83.   register char *s, *t;
  84. {
  85.   register char *u;
  86.  
  87.   if (!t)
  88.     t = s + strlen(s);
  89.   if (f_cpp_cmts) {
  90.     for (u = s; u < t - 1; u++)
  91.       if (*u == '/' && (u[1] == '*' || u[1] == '/'))
  92.     return 1;
  93.   } else {
  94.     for (u = s; u < t - 1; u++)
  95.       if (*u == '/' && u[1] == '*')
  96.     return 1;
  97.   }
  98.   return 0;
  99. }
  100.  
  101. /*
  102.    copy_comment() -- place a malloc()'ed copy of the comment beginning at |s|
  103.    into the global pointer |the_comment|.  Return a pointer to the first
  104.    character after the comment.
  105. */
  106. static char *copy_comment(s)
  107.   register char *s;
  108. {
  109.   register char *in_com, *t;
  110.   register int n;
  111.   register unsigned long in_comment;
  112.  
  113.   in_comment = this_line;
  114.   in_com = the_comment = mallok(len_comment = LINEBUF);
  115.   if (s[1] == '/') {
  116.     free(the_comment);
  117.     the_comment = strdup(s);
  118.     if (w_nest_cmts && nest_check(s + 2, (char *)0))
  119.       warning(SC_nested, in_comment);
  120.     return s + strlen(s);
  121.   }
  122.   for (;;) {
  123.     t = find_end_comment(s);
  124.     n = (!t ? strlen(s) + 2 : (int)(t - s) + 1);
  125.     in_com = grow(&the_comment, &len_comment, in_com, n);
  126.     (void)strncpy(in_com, s, n);
  127.     in_com += n;
  128.     if (!t)
  129.       *in_com++ = '\n';
  130.     *in_com = '\0';
  131.     if (w_nest_cmts && nest_check(s, t))
  132.       warning(SC_nested, in_comment);
  133.     if (t)
  134.       break;
  135.     s = getline();
  136.     if (!s) {
  137.       error(SC_unterm, in_comment);
  138.       in_com = grow(&the_comment, &len_comment, in_com, 3);
  139.       *in_com++ = '*';
  140.       *in_com++ = '/';
  141.       *in_com = '\0';
  142.       t = NULL;
  143.       break;
  144.     }
  145.   }
  146.   return t;
  147. }
  148.  
  149. /*
  150.    suck_comment() -- Skip over the comment beginning at |s|.  Return a
  151.    pointer to the first character after the comment.
  152. */
  153. static char *suck_comment(s)
  154.   register char *s;
  155. {
  156.   register char *t;
  157.   register unsigned long in_comment;
  158.  
  159.   if (keep_comments)
  160.     return copy_comment(s);
  161.   in_comment = this_line;
  162.   /* C++ comments end at the end of the line */
  163.   if (s[1] == '/') {
  164.     if (w_nest_cmts && nest_check(s + 2, (char *)0))
  165.       warning(SC_nested, in_comment);
  166.     return s + strlen(s);
  167.   }
  168.   for (;;) {
  169.     t = find_end_comment(s);
  170.     if (w_nest_cmts && nest_check(s + 2 * (this_line == in_comment), t))
  171.       warning(SC_nested, in_comment);
  172.     if (t) {
  173.       return t;
  174.     }
  175.     s = getline();
  176.     if (!s) {
  177.       error(SC_unterm, in_comment);
  178.       return NULL;
  179.     }
  180.   }
  181. }
  182.  
  183. /*
  184.    suck_ws() -- skip over whitespace characters after |S|, placing them
  185.    into the whitespace field of |T|.  Return a pointer to the first
  186.    non-whitespace character after |s|.
  187. */
  188. char *suck_ws(s, T)
  189.   register char *s;
  190.   TokenP T;
  191. {
  192.   register char *t, *u;
  193.   char *spc_buf;
  194.   size_t sz_spc_buf;
  195.   register int n;
  196.  
  197.   u = spc_buf = mallok(sz_spc_buf = SPC_GRAN);
  198.   for (;;) {
  199.     t = s;
  200.     while (isspace(*s))
  201.       *s++;
  202.     n = (int)(s - t);
  203.     u = grow(&spc_buf, &sz_spc_buf, u, n + 2);
  204.     (void)strncpy(u, t, n);
  205.     u += n;
  206.     *u = '\0';
  207.     if (!(*s == '/' && (s[1] == '*' || (f_cpp_cmts && s[1] == '/'))))
  208.       break;
  209.     s = suck_comment(s);
  210.     if (!keep_comments)
  211.       *u++ = ' ';
  212.     else {
  213.       n = strlen(the_comment);
  214.       u = grow(&spc_buf, &sz_spc_buf, u, n + 1);
  215.       (void)strcpy(u, the_comment);
  216.       free(the_comment);
  217.       u += n;
  218.     }
  219.     if (!s)
  220.       break;
  221.   }
  222.   *u = '\0';
  223.   set_ws(T, spc_buf);
  224.   free(spc_buf);
  225.   return s;
  226. }
  227.